package com.kun.video.thread;

import com.kun.video.context.annotation.Component;
import com.kun.video.exception.BizException;
import com.kun.video.util.ComUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Comparator;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;

/**
 * 通用线程池实现，支持任务优先级调度
 * 特性：
 * 1. 基于优先级的任务队列（数值越大优先级越高）
 * 2. 动态线程池配置（核心线程数=50，最大线程数=100）
 * 3. UI线程任务适配支持
 *
 * @author gzc
 * @since 2025/2/7
 **/
@Component
public class ComThreadPool extends AbstractThreadPool {
    private static final Logger log = LoggerFactory.getLogger(ComThreadPool.class);

    /**
     * 线程名称前缀（用于日志追踪）
     */
    private static final String POOL_THREAD_PREFIX = "pool";

    /**
     * 线程池容量计算因子
     * 公式：1 + 目标IO耗时(500ms) / 目标CPU耗时(20ms)
     * 用于IO密集型场景的线程数估算
     */
    private static final int FACTOR = 1 + 300 / 20; // =16
    /**
     * 可用处理器核心数
     */
    private static final int CPU_CORE = Runtime.getRuntime().availableProcessors();
    /**
     * 核心线程数（固定值50）
     */
    private static final int POOL_CORE_SIZE = CPU_CORE * FACTOR;
    /**
     * 最大线程数（核心线程数的2倍）
     */
    private static final int POOL_MAX_SIZE = POOL_CORE_SIZE * 2;
    /**
     * 非核心线程空闲存活时间（30秒）
     */
    private static final long KEEP_ALIVE_TIME = 30_000L;
    /**
     * 时间单位（毫秒）
     */
    private static final TimeUnit KEEP_ALIVE_TIME_TIME_UNIT = TimeUnit.MILLISECONDS;
    /**
     * 任务队列容量
     */
    private static final int CAPACITY = 1000;

    public ComThreadPool() {
        // 调用父类构造方法初始化线程池
        super();
    }

    /**
     * 创建带有优先级支持的线程池
     *
     * @return 配置完成的 ThreadPoolExecutor 实例
     */
    @Override
    protected ThreadPoolExecutor createPool() {
        // 优先级比较器（数值越大优先级越高）
        Comparator<Runnable> comparator = (r1, r2) -> {
            if (r1 instanceof PrioritizedTask && r2 instanceof PrioritizedTask) {
                // 倒序排列
                return Integer.compare(
                        ((PrioritizedTask) r2).getPriority(),
                        ((PrioritizedTask) r1).getPriority()
                );
            }
            if (r1 instanceof PriorityFutureTask && r2 instanceof PriorityFutureTask) {
                return Integer.compare(
                        ((PriorityFutureTask<?>) r2).getPrioritizedTask().getPriority(),
                        ((PriorityFutureTask<?>) r1).getPrioritizedTask().getPriority()
                );
            }
            log.warn("""
                            线程池任务优先级排序异常：
                            任务类型1: {}
                            任务类型2: {}
                            可能原因：
                            1. 任务未封装为PriorityFutureTask/PrioritizedTask
                            2. 任务被调用线程直接执行（超过线程池容量）""",
                    r1.getClass(), r2.getClass());
            // 默认按提交顺序处理
            return -1;
        };

        return new PriorityThreadPoolExecutor(
                POOL_CORE_SIZE,
                POOL_MAX_SIZE,
                KEEP_ALIVE_TIME,
                KEEP_ALIVE_TIME_TIME_UNIT,
                new PriorityBlockingQueue<>(CAPACITY, comparator),
                // 自定义线程命名
                new NamedThreadFactory(POOL_THREAD_PREFIX),
                // 饱和策略
                new ThreadPoolExecutor.CallerRunsPolicy());
    }

    //------------------------- 任务提交方法重写（优先级支持） -------------------------

    /**
     * 提交带优先级的Callable任务
     *
     * @param task 待执行任务（自动包装为优先级任务）
     * @return Future对象
     */
    @Override
    public <T> Future<T> submit(Callable<T> task) {
        FutureTask<T> futureTask = new FutureTask<>(task);
        execute(futureTask);
        return futureTask;
    }

    /**
     * 提交Runnable任务（自动添加优先级包装）
     *
     * @param task 待执行任务（非优先级的会被自动包装）
     * @return Future对象
     */
    @Override
    public Future<?> submit(Runnable task) {
        return task instanceof PrioritizedTask ?
                pool.submit(task) :
                pool.submit(new PrioritizedTask(task));
    }

    /**
     * 提交UI线程任务（带优先级支持）
     *
     * @param task UI操作任务
     * @return Future对象
     */
    @Override
    public Future<?> submitUI(Runnable task) {
        Runnable wrapper = () -> ComUtil.uiThreadRun(task);
        return submit(new PrioritizedTask(wrapper));
    }

    /**
     * 执行任务（自动添加优先级包装）
     *
     * @param task 待执行任务
     */
    @Override
    public void execute(Runnable task) {
        pool.execute(task instanceof PrioritizedTask ?
                task :
                new PrioritizedTask(task));
    }

    //------------------------- CompletableFuture 增强实现 -------------------------

    /**
     * 异步执行任务（优先级支持）
     *
     * @param runnable 待执行任务
     * @return CompletableFuture对象
     */
    @Override
    public CompletableFuture<Void> runAsync(Runnable runnable) {
        return CompletableFuture.runAsync(runnable, this::execute);
    }

    /**
     * 带优先级的异步执行方法
     *
     * @param prioritizedTask 优先级任务对象
     * @return CompletableFuture对象
     */
    public CompletableFuture<Void> runAsync(PrioritizedTask prioritizedTask) {
        return CompletableFuture.runAsync(prioritizedTask, pool);
    }

    /**
     * 带优先期的异步获取方法
     *
     * @param priorityFutureTask 优先级FutureTask
     * @return CompletableFuture对象
     */
    public <T> CompletableFuture<T> supplyAsync(PriorityFutureTask<T> priorityFutureTask) {
        CompletableFuture<T> future = new CompletableFuture<>();
        execute(() -> {
            try {
                priorityFutureTask.run();
                future.complete(priorityFutureTask.get());
            } catch (Throwable t) {
                future.completeExceptionally(t);
            }
        });
        return future;
    }

    /**
     * UI线程异步执行（注意：会阻塞当前线程）
     *
     * @param supplier UI操作
     * @return CompletableFuture对象
     */
    @Override
    public <T> CompletableFuture<T> supplyAsyncUI(Supplier<T> supplier) {
        return supplyAsync(() -> {
            AtomicReference<T> result = new AtomicReference<>();
            ComUtil.uiThreadRun(() -> {
                try {
                    result.set(supplier.get());
                } catch (Exception e) {
                    throw new BizException("UI线程执行失败", e);
                }
            });
            // 阻塞当前线程直到UI操作完成
            return result.get();
        });
    }
}